#include <math.h>
#include "bangdots.h"
#include "random_gen.h"
#include "rockdodger_globals.h"

#ifdef DEBUG
#include <stdio.h>
static unsigned long max_bangdots_used = 0;
#endif

static struct bangdots bdots[MAX_BANG_DOTS];
static struct bangdots *bdots_end = bdots;

void makebangdots(int xbang, int ybang, int xvel, int yvel, SDL_Surface * s,
		  int power, int amtdots) {
  // TODO - stop generating dots after a certain amount of time has passed, to cope with slower CPUs.
  int x, y, endcount;
  RD_VIDEO_TYPE *rawpixel, c;
  double theta, r;
  int begin_generate;

  begin_generate = SDL_GetTicks();
  SDL_LockSurface(s);
  rawpixel = (RD_VIDEO_TYPE *) s->pixels;
  endcount = 0;
  while(endcount < amtdots) {
    for(x = 0; x < s->w; x++) {
      for(y = 0; y < s->h; y++) {
	c = rawpixel[s->pitch / 2 * y + x];
	if(c && c != SDL_MapRGB(s->format, 0, 255, 0)) {

	  if(++bdots_end - bdots >= MAX_BANG_DOTS)
	    goto exitloop;
	  theta = rnd() * M_PI * 2;
	  r = 1 - (rnd() * rnd());
	  bdots_end->dx = (power / 50.0) * 45.0 * cos(theta) * r + xvel;
	  bdots_end->dy = (power / 50.0) * 45.0 * sin(theta) * r + yvel;
	  bdots_end->x = x + xbang;
	  bdots_end->y = y + ybang;
	  // Replace the last few bang dots with the pixels from the exploding object
	  bdots_end->c = (endcount > 0) ? c : 0;
	  bdots_end->life = 100;
	  bdots_end->decay = rnd() * 3 + 1;
	}
      }
    }
    if(SDL_GetTicks() - begin_generate > 3)
      endcount++;
  }
exitloop:
#ifdef DEBUG
  x = bdots_end - bdots;
  if(x > max_bangdots_used) {
    max_bangdots_used = x;
    printf("new: max_bangdots_used = $%lX\n", max_bangdots_used);
  }
#endif
  SDL_UnlockSurface(s);
}


void draw_bang_dots(SDL_Surface * s) {
  RD_VIDEO_TYPE *rawpixel;
  struct bangdots *bdot;

  rawpixel = (RD_VIDEO_TYPE *) s->pixels;
  for(bdot = bdots; bdot < bdots_end; ++bdot) {
    rawpixel[(int) (s->pitch / 2 * (int) (bdot->y)) + (int) (bdot->x)]
      = bdot->c ? bdot->c : heatcolor[(int) (bdot->life * 3)];
  }
}

void update_bangdots(SDL_Surface * s) {
  RD_VIDEO_TYPE *rawpixel, *r;
  struct bangdots bdot;
  struct bangdots *ptr;
  struct bangdots *target = bdots;

  SDL_LockSurface(s);
  rawpixel = (RD_VIDEO_TYPE *) s->pixels;
  for(ptr = bdots; ptr < bdots_end; ++ptr) {
    bdot = *ptr;
    /*
     * Kill all the dots which collide with other objects.
     */
    if(bdot.life < 87) {
      r = &rawpixel[(int) (s->pitch / 2 * (int) (bdot.y)) + (int) (bdot.x)];
      if(*r != (bdot.c ? bdot.c : heatcolor[(int) (bdot.life * 3)])) {
	// Continue and do not copy
	continue;
      }
    }
    bdot.life -= bdot.decay * movementrate;
    if(bdot.life < 0)
      continue;
    bdot.x += bdot.dx * movementrate;
    bdot.y += bdot.dy * movementrate;
    if(bdot.x <= 0 || bdot.x >= xsize || bdot.y <= 0 || bdot.y >= ysize) {
      // If the dot has drifted outside the perimeter, kill it
      continue;
    }
    *target++ = bdot;
  }
  SDL_UnlockSurface(s);
  bdots_end = target;
}
